/**
  ******************************************************************************
  * @file    socket-util.h
  * @author  Dragon.Chen
  * @version V1.0.2
  * @date    11-08-2013
  * @brief   socket通用函数接口
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2018 上海今中网络科技有限公司 </center></h2>
  ******************************************************************************
  */

#ifndef __SOCKET_UTIL__H__
#define __SOCKET_UTIL__H__

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#define closesocket  close

/// 发送数据到服务器
#define SEND_COMMAND(serverfd) \
		while (TRUE) \
		{ \
			retval = send(serverfd, \
						  clientInfo->buffer       + clientInfo->bufferPosition, \
						  clientInfo->bufferLength - clientInfo->bufferPosition, \
						  0); \
			if (retval < 0) \
			{ \
				if (errno == EINTR) \
				{ \
					continue; \
				} \
				else if (errno == EAGAIN || errno == EWOULDBLOCK) \
				{ \
					clientInfo->bufferFirst = NO; \
					return 1; \
				} \
				else \
				{ \
					return -1; \
				} \
			} \
			else if (retval == 0) \
			{ \
				return -1; \
			} \
\
			clientInfo->bufferPosition += retval; \
			if (clientInfo->bufferPosition < clientInfo->bufferLength) \
			{ \
				continue; \
			} \
			else if (clientInfo->bufferPosition == clientInfo->bufferLength) \
			{ \
				clientInfo->bufferFirst = YES; \
				return 0; \
			} \
			else \
			{ \
				return -1; \
			} \
		}


/// 从服务器接收数据
#define RECV_COMMAND(serverfd) \
		if (clientInfo->bufferFirst == YES) \
		{ \
			ZeroMemory(clientInfo->buffer, SOCK_RECV_MAXBUF); \
			clientInfo->bufferPosition = 0;\
			retval = recv(serverfd, \
						  clientInfo->buffer, \
						  CLIENT_DATA_PACK_HEADLEN, \
						  0); \
			if ( (retval != CLIENT_DATA_PACK_HEADLEN) || \
			    ((clientInfo->bufferLength = atoi(clientInfo->buffer)) == 0) ) \
			{ \
				return -1; \
			} \
		} \
\
		while (TRUE)\
		{ \
			retval = recv(serverfd,   \
						  clientInfo->buffer       + clientInfo->bufferPosition, \
						  clientInfo->bufferLength - clientInfo->bufferPosition, \
						  0);\
			if (retval <0) \
			{ \
				if (errno == EINTR) \
				{ \
					continue; \
				} \
				else if (errno == EAGAIN || errno == EWOULDBLOCK) \
				{ \
					clientInfo->bufferFirst = NO; \
					return 1; \
				} \
				else \
				{ \
					return -1; \
				} \
			} \
			else if (retval == 0) \
			{ \
				return -1; \
			} \
\
			clientInfo->bufferPosition += retval; \
			if (clientInfo->bufferPosition < clientInfo->bufferLength) \
			{ \
				continue; \
			} \
			else if (clientInfo->bufferPosition == clientInfo->bufferLength) \
			{ \
				char _data_head[5] = {0}; \
				strncpy(_data_head, clientInfo->buffer, 4); \
				datapack = (DATA_PACK_T*)clientInfo->buffer; \
				datapack->head = atoi(_data_head); \
				clientInfo->bufferFirst = YES; \
				break; \
			} \
			else \
			{ \
				return -1; \
			} \
		}


/// 发送文件
#define SEND_FILE(serverfd) \
		while (TRUE) \
		{ \
			retval = send(serverfd, \
		    (const char *)clientInfo->fileInfo.buffer + clientInfo->fileInfo.position, \
						  clientInfo->fileInfo.length - clientInfo->fileInfo.position, \
						  0); \
			if (retval < 0) \
			{ \
				if (errno == EINTR) \
				{ \
					continue; \
				} \
				else if (errno == EAGAIN || errno == EWOULDBLOCK) \
				{ \
					clientInfo->bufferFirst = NO; \
					return 1; \
				} \
				else \
				{ \
					return -1; \
				} \
			} \
			else if (retval == 0) \
			{ \
				return -1; \
			} \
\
			clientInfo->fileInfo.position += retval; \
			if (clientInfo->fileInfo.position < clientInfo->fileInfo.length) \
			{ \
				continue; \
			} \
			else if (clientInfo->fileInfo.position == clientInfo->fileInfo.length) \
			{ \
				clientInfo->bufferFirst = YES; \
				return 0; \
			} \
			else \
			{ \
				return -1; \
			} \
		}

/// 接收文件
#define RECV_FILE(serverfd) \
			if (clientInfo->bufferFirst == YES) \
			{  \
				ZeroMemory(clientInfo->buffer, SOCK_RECV_MAXBUF); \
				clientInfo->fileInfo.position= 0; \
				retval = recv(serverfd,\
							  clientInfo->buffer,  \
							  CLIENT_DATA_PACK_HEADLEN, \
							  0);\
				if ( (retval != CLIENT_DATA_PACK_HEADLEN) || \
					((clientInfo->fileInfo.length = atoi(clientInfo->buffer)) == 0) ) \
				{ \
					retval = -1; \
					goto cleanup; \
				} \
\
				clientInfo->fileInfo.buffer = (char *)calloc(clientInfo->fileInfo.length+1, 1); \
				if (clientInfo->fileInfo.buffer == NULL) \
				{ \
					retval = -1; \
					goto cleanup; \
				} \
			} \
\
			while (TRUE)  \
			{ \
				retval = recv(clientInfo->serverFd, \
					  (char *)clientInfo->fileInfo.buffer + clientInfo->fileInfo.position, \
							  clientInfo->fileInfo.length - clientInfo->fileInfo.position, \
							  0); \
				if (retval <0) \
				{ \
					if (errno == EINTR) \
					{ \
						continue; \
					} \
					else if (errno == EAGAIN || errno == EWOULDBLOCK) \
					{ \
						clientInfo->bufferFirst = NO; \
						return 1; \
					} \
					else \
					{ \
						retval = -1; \
						goto cleanup; \
					} \
				} \
				else if (retval == 0) \
				{ \
					retval = -1; \
					goto cleanup; \
				} \
\
				clientInfo->fileInfo.position += retval; \
				if (clientInfo->fileInfo.position < clientInfo->fileInfo.length) \
				{ \
					continue; \
				} \
				else if (clientInfo->fileInfo.position == clientInfo->fileInfo.length) \
				{ \
					clientInfo->bufferFirst = YES; \
					break; \
				} \
				else \
				{ \
					retval = -1; \
					goto cleanup; \
				} \
			}

/**
  * @brief  设置socket阻塞状态
  * @param  arg1:fd
  * @retval	成功返回0, 失败返回-1
  */
int setblocking(int fd);

/**
  * @brief  设置描述符为非阻塞状态
  * @param  arg1:fd  arg2:标记
  * @retval	成功返回0, 失败返回-1
  */
int setnonblocking(int fd);

/**
  * @brief  非阻塞连接
  * @param  arg1 ip  arg2 port arg3 超时时间
  * @retval 返回监听fd,失败程序exit
  */
int tcp_connect(const char *ip, int port, int time);

#endif

/******************* (C) COPYRIGHT 2018 上海今中网络科技有限公司 *****END OF FILE****/

